import { Util, throttle } from '@ibizstudio/runtime';
import { TreeControlBase } from '../../../widgets';
import { IPSDETreeNode, IPSDEContextMenu } from '@ibizstudio/runtime';

/**
 * 树视图部件基类
 *
 * @export
 * @class AppTreeViewBase
 * @extends {TreeControlBase}
 */
export class AppTreeViewBase extends TreeControlBase {
  /**
   * 绘制右击菜单
   *
   * @param {*} node
   * @returns
   * @memberof AppTreeViewBase
   */
  renderContextMenu(node: any) {
    if (node && node.data) {
      const data: any = JSON.parse(JSON.stringify(node.data));
      this.currentselectedNode = { ...data };
      const tags: string[] = data.id.split(';');
      let treeNodes = this.controlInstance.getPSDETreeNodes() || [];
      let treeNode = treeNodes.find((node: IPSDETreeNode) => tags[0] == node.nodeType) as IPSDETreeNode;
      let contextMenu = treeNode.getPSDEContextMenu() as IPSDEContextMenu;
      if (contextMenu && contextMenu.controlType == 'CONTEXTMENU') {
        let { targetCtrlName, targetCtrlParam, targetCtrlEvent }: { targetCtrlName: string; targetCtrlParam: any; targetCtrlEvent: any } = this.computeTargetCtrlData(contextMenu);
        targetCtrlParam.dynamicProps.contextMenuActionModel = this.copyActionModel;
        Object.assign(targetCtrlEvent, {
          'ctrl-event': ({ controlname, action, data }: { controlname: string; action: string; data: any }) => {
            this.onCtrlEvent(controlname, action, data, Util.deepCopy(this.currentselectedNode));
          },
        });
        return this.$createElement(targetCtrlName, { props: targetCtrlParam, ref: contextMenu.name, on: targetCtrlEvent });
      }
    }
    return null;
  }

  /**
   * 绘制内容
   *
   * @returns
   * @memberof AppTreeViewBase
   */
  renderNode({ node, data }: any): any {
    // 绘制图标
    let iconElement = null;
    if (data.iconCustomCode) {
      let icon = '';
      if (data.iconScriptCode.indexOf('return') !== -1) {
        data.iconScriptCode = data.iconScriptCode.replace(new RegExp('return', 'g'), `icon =`);
      }
      eval(data.iconScriptCode);
      iconElement = <span domPropsInnerHTML={icon}></span>;
    } else if (data.iconcls) {
      iconElement = <i class={data.iconcls}></i>;
    } else if (data.icon) {
      iconElement = <ion-icon style='transform:translateY(1px);' src={data.icon} />;
    } else if (this.controlInstance.outputIconDefault) {
      iconElement = <i class='ivu-icon ivu-icon-ios-paper-outline'></i>;
    }
    const cssName = data.cssName ? data.cssName : '';
    const nodeStyle = {
      width: '100%',
      'padding-left': node.parent?.data?.enablecheck && !node.data?.enablecheck ? '22px' : '0px',
    };
    if (this.ctrlTriggerLogicMap.get('calcnodestyle')) {
      let styleObj = this.ctrlTriggerLogicMap.get('calcnodestyle').executeUILogic({ arg: { node, data } });
      Object.assign(nodeStyle, styleObj);
    }
    // 绘制显示文本
    let textElement = null;

    if (data.textCustomCode) {
      let text = '';
      if (data.textScriptCode.indexOf('return') !== -1) {
        data.textScriptCode = data.textScriptCode.replace(new RegExp('return', 'g'), `text =`);
      }
      eval(data.textScriptCode);
      textElement = <span domPropsInnerHTML={text}></span>;
    } else if (data.html) {
      textElement = <span domPropsInnerHTML={data.html}></span>;
    } else {
      textElement = <span>{Object.is(data.nodeType, 'STATIC') ? this.$tl(data.lanResTag, data.text) : data.text}</span>;
    }

    // 计数器
    let nodeCount: any = undefined;
    if (this.controlInstance.getPSAppCounterRef()?.id) {
      let counterService = Util.findElementByField(this.counterServiceArray, 'id', this.controlInstance.getPSAppCounterRef()?.id)?.service;
      nodeCount = counterService?.counterData?.[data.counterId];
    }
    let nodeCountStyle = {
      count: nodeCount,
      showZero: data.counterMode !== 1,
      offset: [4, 7],
    };

    return (
      <context-menu
        ref={data.id}
        isBlocked={true}
        contextMenuStyle={nodeStyle}
        data={node}
        renderContent={this.renderContextMenu.bind(this)}
        on-showContext={(e: any) => {
          this.showContext(data, e);
        }}
      >
        <div
          class={['tree-node', cssName]}
          title={data.tooltip ? data.tooltip : Object.is(data.nodeType, 'STATIC') ? this.$tl(data.lanResTag, data.text) : data.text}
          v-badge={nodeCountStyle}
          on-dblclick={() => {
            throttle(this.doDefaultAction, [node], this);
          }}
        >
          {iconElement ? <span class='icon'>{iconElement}</span> : null}
          <span class='text'>{textElement}</span>
        </div>
      </context-menu>
    );
  }

  /**
   * 绘制内容
   *
   * @returns
   * @memberof AppTreeViewBase
   */
  render(): any {
    if (!this.controlIsLoaded || !this.inited) {
      return null;
    }
    const { controlClassNames } = this.renderOptions;
    return (
      <div class={{ 'design-tree-container': true, ...controlClassNames }}>
        <context-menu-container>
          <app-element-tree
            ref={this.name}
            class='design-tree'
            node-key='id'
            lazy
            show-checkbox={!this.isSingleSelect}
            check-on-click-node={!this.isSingleSelect}
            default-expanded-keys={this.expandedKeys}
            props={{
              props: {
                label: 'text',
                isLeaf: 'leaf',
                children: 'children',
              },
            }}
            draggable={this.draggable}
            allow-drag={(node: any) => {
              return throttle(this.allowDrag, [node], this);
            }}
            allow-drop={(draggingNode: any, dropNode: any, type: string) => {
              return this.allowDrop(draggingNode, dropNode, type);
            }}
            on-edit-value-change={(value: string, node: any, event: any) => {
              this.nodeValueChange(value, node, event);
            }}
            on-close-edit={(node: any, event: any) => {
              this.saveAndRefresh(node, event);
            }}
            load={this.load.bind(this)}
            highlight-current={true}
            expand-on-click-node={false}
            on-check={(data: any, checkedState: any) => {
              this.onCheck(data, checkedState);
            }}
            on-current-change={this.selectionChange.bind(this)}
            filter-node-method={this.filterNode.bind(this)}
            empty-text={this.$t('app.commonwords.nodata')}
            scopedSlots={{
              default: this.renderNode.bind(this),
            }}
          ></app-element-tree>
        </context-menu-container>
      </div>
    );
  }
}
